package auctionhaus

import org.springframework.dao.DataIntegrityViolationException
import grails.plugins.springsecurity.Secured
import grails.util.Environment;


class BidController {

	/**
	 * SRV-4: Refactor your Controllers from the previous assignments to use the service methods created in this section (unit test)
	 */
	CrudService crudService;
	static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

	def index() {
		redirect(action: "list", params: params)
	}

	def list() {
		params.max = Math.min(params.max ? params.int('max') : 5, 100)
		[bidInstanceList: Bid.list(params), bidInstanceTotal: Bid.count()]
	}


	/**
	 * UI-1: The listing detail page will asynchronously load and display a list of the last 10 bids placed on the item showing the user, date/time, and amount.
	 * The implementation of the lookup of these results must be done with a Named Query. (Integration Test)
	 */

	def showRecentBids() {
		
		Long listingID = Long.parseLong(params.listingID)

		def bids = Bid.listingRecentBids(listingID).list();

		[bidInstanceList: bids, bidInstanceTotal: bids.size()]
	}


	def hideRecentBids() {
		render ""
	}


	def saveBidAndReturnDetailsAjax(){

		Listing l = Listing.findById(params['listing.id']);
		Date now = new Date();

		/**
		 * UI-7: Attempting to view the listing detail page for a listing that has expired will display a "Listing Expired" message instead of showing the details of the listing
		 */
		if(now.after(l.endDateTime)){

			render ("<br/><div><H1>&nbsp&nbsp&nbsp&nbsp"+message(code: 'listing.expired', default: 'Listing is Expired, Please Find Another Listing.')+"</H1></div><br/><br/>");
			return
		}

		if(params.containsKey("listingLoad")){
			return [listingInstance:l]
		}


		if(!Environment.getCurrentEnvironment().equals(Environment.TEST))
			params['bidder.id'] = getAuthenticatedUser().id

		def bidInstance = new Bid(params)

		if (!crudService.createBid(bidInstance)) {
			//render(view: "create", model: [bidInstance: bidInstance])

			if(bidInstance==null||bidInstance.listing==null||bidInstance.listing.bids==null){
				flash.message = message(code: "bids.invalid",args:[]);
				//				redirect(action: "show", controller:"listing", id: 0)
				l.getBids().remove(bidInstance)
				return [listingInstance:l]
			}
			//C-3 When a listing completes it can no longer accept any more bids.  Verify this by testing through the service method created for SRV-3 (unit test).
			else if(now.after(l.endDateTime))
			{
				flash.message = message(code: 'bids.cannot.be.placed',args: [
					bidInstance.listing.endDateTime
				]);
			}
			else{

				//L-8: Validation errors will be displayed on the listing detail page if an added bid does not pass validation (unit test of the controller action that handles this requirement)

				flash.message = message(code: 'bids.invalid.amount',args: [
					Bid.amountFormatter(bidInstance.amount),
					Bid.amountFormatter(bidInstance.listing.currentMinimumBid)
				]);


			}

			l.getBids().remove(bidInstance)
			return [listingInstance:l]
		}

		if(bidInstance.validate()&&(bidInstance.listing.currentMinimumBid <= bidInstance.amount)){
			bidInstance.listing.currentMinimumBid = bidInstance.amount+Bid.BID_INC;
			crudService.updateListing(bidInstance.listing)
		}

		flash.message = message(code: 'default.created.message', args: [
			message(code: 'bid.label', default: 'Bid'),
			bidInstance.id
		])

		return [listingInstance:l]
	}
	
	/*
	 * S-3: Bidding on an item requires that the user be logged in
	 */
	@Secured(['ROLE_USER', 'ROLE_ADMIN'])
	def createAjax() {
		[bidInstance: new Bid(params)]
	}


	@Secured(['ROLE_USER', 'ROLE_ADMIN'])
	def create() {
		[bidInstance: new Bid(params)]
	}

	def save() {

		if(!Environment.getCurrentEnvironment().equals(Environment.TEST))
			params['bidder.id'] = getAuthenticatedUser().id

		def bidInstance = new Bid(params)


		if (!crudService.createBid(bidInstance)) {
			//render(view: "create", model: [bidInstance: bidInstance])

			if(bidInstance==null||bidInstance.listing==null||bidInstance.listing.bids==null){
				flash.message = message(code: "bids.invalid",args:[]);
				redirect(action: "show", controller:"listing", id: 0)
				return
			}
			else{

				//L-8: Validation errors will be displayed on the listing detail page if an added bid does not pass validation (unit test of the controller action that handles this requirement)
				flash.message = message(code: 'bids.invalid.amount',args: [
					Bid.amountFormatter(bidInstance.amount),
					Bid.amountFormatter(bidInstance.listing.currentMinimumBid)
				]);

			}

			redirect(action: "show", controller:"listing", id: bidInstance.listing.id)
			return
		}

		bidInstance.listing.currentMinimumBid = bidInstance.amount+Bid.BID_INC;
		crudService.updateListing(bidInstance.listing)

		flash.message = message(code: 'default.created.message', args: [
			message(code: 'bid.label', default: 'Bid'),
			bidInstance.id
		])
		redirect(action: "show", controller:"listing", id: bidInstance.listing.id)
	}

	def show() {
		def bidInstance = Bid.get(params.id)
		if (!bidInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'bid.label', default: 'Bid'),
				params.id
			])
			redirect(action: "list")
			return
		}

		[bidInstance: bidInstance]
	}

	@Secured(['ROLE_ADMIN'])
	def edit() {
		def bidInstance = Bid.get(params.id)
		if (!bidInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'bid.label', default: 'Bid'),
				params.id
			])
			redirect(action: "list")
			return
		}

		[bidInstance: bidInstance]
	}

	@Secured(['ROLE_ADMIN'])
	def update() {
		def bidInstance = Bid.get(params.id)
		if (!bidInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'bid.label', default: 'Bid'),
				params.id
			])
			redirect(action: "list")
			return
		}

		if (params.version) {
			def version = params.version.toLong()
			if (bidInstance.version > version) {
				bidInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
						[
							message(code: 'bid.label', default: 'Bid')]
						as Object[],
						"Another user has updated this Bid while you were editing")
				render(view: "edit", model: [bidInstance: bidInstance])
				return
			}
		}

		bidInstance.properties = params

		if (!crudService.updateBid(bidInstance)) {
			render(view: "edit", model: [bidInstance: bidInstance])
			return
		}

		flash.message = message(code: 'default.updated.message', args: [
			message(code: 'bid.label', default: 'Bid'),
			bidInstance.id
		])
		redirect(action: "show", id: bidInstance.id)
	}

	@Secured(['ROLE_ADMIN'])
	def delete() {
		def bidInstance = Bid.get(params.id)
		if (!bidInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'bid.label', default: 'Bid'),
				params.id
			])
			redirect(action: "list")
			return
		}

		try {
			crudService.deleteBid(bidInstance)
			flash.message = message(code: 'default.deleted.message', args: [
				message(code: 'bid.label', default: 'Bid'),
				params.id
			])
			redirect(action: "list")
		}
		catch (DataIntegrityViolationException e) {
			flash.message = message(code: 'default.not.deleted.message', args: [
				message(code: 'bid.label', default: 'Bid'),
				params.id
			])
			redirect(action: "show", id: params.id)
		}
	}
}
